react-router-dom react.lazy react-transition-group

  • 邢毅彪
  • 14 Minutes
  • 2020年3月2日

前言

最近组内在使用react重构之前的老项目, 遇到个很典型的需求,异步加载页面和页面过场动画结合。 组内大佬找了一下, 没找到合适的方法,我就自己也试了一下。view url

实现思路

异步加载组件和代码切割使用的是官方提供的Suspense, lazy

实现比较简单

1
2
const Hello = lazy(() => import("./views/hello"));
const Home = lazy(() => import("./views/home"));

路由使用的是react-router-dom@5.1.2

动画使用的是react-transition-group

话不多说直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<Route
render={({ location }) => (
<TransitionGroup>
<CSSTransition
key={location.pathname}
classNames={forward ? "forward" : "back"}
appear
timeout={5000}
>
<Switch location={location}>
{routes.map(r => {
return (
<Route exact={r.exact} path={r.path} key={r.path}>
{wrap(r.Component)}
</Route>
);
})}
</Switch>
</CSSTransition>
</TransitionGroup>
)}
/>

这里兼具了动态路由的实现, 没有完全使用官方文档的jsx配置思路,使用json对象配置比较灵活, 可以做一些类似根据权限动态生成, 根据打包参数动态打包路由等骚操作。

顺便实现了一个简易的eventBus, 有一次面试问到实现,这次重新组织了一下数据结构,bus使用二维数组实现, 更加扁平, 仅供参考.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
type EventBus = {
bus: Array<string | Function>[];
emit: (evt: string, payload?: any) => void;
on: (evt: string, listener: Function) => void;
off: (evt: string, listener: Function) => void;
};

const eventBus: EventBus = {
bus: [],
emit(evt: string, payload?: any) {
const { bus } = eventBus;
let i = 0;
while (i < bus.length) {
if (!bus[i]) {
i++;
continue;
}
const [name, ...listeners] = bus[i];
console.log(evt, name, listeners, i);
if (name && listeners.length) {
if (name === evt) {
listeners.forEach(listener => {
if (typeof listener === "function") {
console.log("before call", listener);
listener(payload);
}
});
}
}
i++;
}
},
on(evt: string, listener: Function) {
const { bus } = eventBus;
if (!bus.length) {
bus.push([evt, listener]);
return;
}
let i = 0;
let has = false;
while (i < bus.length) {
i++;
if (!bus[i]) continue;
const [name, ...listeners] = bus[i];
if (name === evt) {
if (listeners.indexOf(listener) <= 0) {
has = true;
bus[i].push(listener);
}
}
}
if (!has) {
bus.push([evt, listener]);
}
},
off(evt: string, listener: Function) {
const { bus } = eventBus;
let i = 0;
if (!bus.length) return;

while (i < bus.length) {
i++;
if (!bus[i]) continue;
const [name, ...listeners] = bus[i];
if (evt === name) {
const index = listeners.findIndex(l => l === listener);
listeners.splice(index, 1);
}
}
}
};

写在最后

其实看似简单的需求和功能, 足足花费了我大半天, 说明自己对于react生态还是不熟悉, 所以特此记录下来。github

访问量